import random
import threading
import time
from flask import jsonify
import requests
import json
from datetime import datetime
import math
# 在原有导入语句基础上添加以下内容
from pymongo import MongoClient
import mysql.connector
from mysql.connector import Error

# ------------------- 设备数据类 -------------------
class ShoeDevice:
    def __init__(self, device_id, mode="年轻人步行"):
        self.device_id = device_id
        self.enabled = True
        self.history_length = 60   # 60 data points, about 2 minutes of data
        self.hr_history = [None] * self.history_length
        self.temp_history = [None] * self.history_length
        self.mode = mode  # Simulation mode
        self.reset_data()

    def update_mode_parameters(self):
        if self.mode == "静息状态":
            self.base_hr = random.randint(50, 60)
            self.base_stride = 0.0
            self.stride_frequency = 0.0
        elif self.mode == "老年人步行":
            self.base_hr = random.randint(60, 70)
            self.base_stride = 0.6 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 1.2
        elif self.mode == "年轻人步行":
            self.base_hr = random.randint(70, 80)
            self.base_stride = 0.8 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 1.5
        elif self.mode == "慢跑":
            self.base_hr = random.randint(90, 110)
            self.base_stride = 1.0 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 2.0
        elif self.mode == "快速跑步":
            self.base_hr = random.randint(110, 130)
            self.base_stride = 1.2 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 2.5
        elif self.mode == "运动员训练":
            self.base_hr = random.randint(130, 150)
            self.base_stride = 1.3 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 3.0
        else:
            self.base_hr = random.randint(70, 80)
            self.base_stride = 0.8 + random.uniform(-0.05, 0.05)
            self.stride_frequency = 1.5
        self.base_temp = 37.0

    def reset_data(self):
        self.cycle_counter = 0
        self.linear_counter = 0
        self.update_mode_parameters()
        self.heartrate = self.base_hr
        self.stride_length = self.base_stride
        self.temperature = self.base_temp
        self.connected = True
        self.last_update = datetime.now()
        self.last_data = None

    def _generate_stride_frequency(self):
        if self.mode == "静息状态":
            self.stride_frequency = 0.0
        else:
            freq = self.stride_frequency + (self.heartrate - self.base_hr) / 50.0 + random.gauss(0, 0.05)
            self.stride_frequency = max(1.0, min(round(freq, 2), 3.0))

    def generate_data(self, global_connected):
        if self.enabled and global_connected:
            self.connected = True
            self._generate_heartrate()
            self._generate_stride()
            self._generate_temperature()
            self._generate_stride_frequency()
            self._update_history()
        else:
            self.connected = False
            self.heartrate = 60
            self.stride_length = 0.0
            self.stride_frequency = 0.0
            self.temperature = 36.0
        self.last_update = datetime.now()
        self.last_data = self.get_data_dict()

    def _generate_heartrate(self):
        noise = random.gauss(0, 1)
        self.heartrate = self.base_hr + 3 * math.sin(self.cycle_counter / 6) + noise
        self.cycle_counter += 1
        upper_limit = 150 if self.mode != "静息状态" else 80
        self.heartrate = max(50, min(round(self.heartrate), upper_limit))

    def _generate_stride(self):
        if self.mode == "静息状态":
            self.stride_length = 0.0
        else:
            noise = random.gauss(0, 0.05)
            self.stride_length = self.base_stride + noise
            self.stride_length = round(max(0.5, min(self.stride_length, 1.5)), 2)

    def _generate_temperature(self):
        noise = random.gauss(0, 0.2)
        self.temperature = self.base_temp + noise
        self.temperature = round(max(36.5, min(self.temperature, 37.5)), 1)

    def _update_history(self):
        self.hr_history = self.hr_history[1:] + [self.heartrate]
        self.temp_history = self.temp_history[1:] + [self.temperature]

    def get_data_dict(self):
        return {
            "record_time": self.last_update.strftime("%Y-%m-%d %H:%M:%S"),
            "device_id": self.device_id,
            "heart_rate": self.heartrate,
            "stride_length": self.stride_length,
            "stride_frequency": self.stride_frequency,
            "temperature": self.temperature,
            "connection_status": self.connected,
            "enabled": self.enabled,
            "mode": self.mode
        }

# ------------------- 上传数据函数 -------------------
import random

def send_data_to_server(data):
    print(data)
    url = "http://8.137.20.120:5000/api/data/upload"
    headers = {"Content-Type": "application/json"}
    max_retries = 5
    retries = 0
    
    while retries < max_retries:
        try:
            response = requests.post(url, json=data, headers=headers, timeout=30)
            response.raise_for_status()  # 检查 HTTP 状态码
            print("Server response:", response.json())
            return True
        except Exception as e:
            wait_time = 2 ** retries + random.uniform(0, 1)  # 指数退避 + 随机抖动
            print(f"Error sending data (attempt {retries + 1}): {e}")
            print(f"Retrying in {wait_time:.2f} seconds...")
            time.sleep(wait_time)
            retries += 1
    
    print("Failed to send data after multiple attempts.")
    return False
# ------------------- 数据生成和上传线程函数 -------------------
def device_worker(device, running, global_connected):
    while running[0]:
        if device.enabled and global_connected[0]:
            device.generate_data(global_connected[0])
            data = device.get_data_dict()
            # 上传数据到服务器
            send_data_to_server(data)
            log_msg = (f"Device {device.device_id} | HR: {device.heartrate} | "
                       f"Stride: {device.stride_length:.2f} | Temp: {device.temperature:.1f}°C | "
                       f"{datetime.now():%Y-%m-%d %H:%M:%S}\n")
            print(log_msg)
        time.sleep(30)  # 
# MongoDB 连接[{role:"dbAdminAnyDatabase",db:"admin"}]});
try:
    username = "iot_admin"
    password = "Ylt20250015"
    mongo_client = MongoClient(f'mongodb://{username}:{password}@8.137.20.120:27017/',serverSelectionTimeoutMS=5000)
    mongo_client.admin.command('ping')
    mongo_db = mongo_client['iot_data_db']
    mongo_collection = mongo_db['device_records']
except Exception as e:
    print(f"MongoDB 连接失败: {e}")

# MySQL 连接
try:
    mysql_connection = mysql.connector.connect(
        host='8.137.20.120',
        port=3306,
        database='iot_data',
        user='root',
        password='liuzheyu2268'
    )
    if mysql_connection.is_connected():
        mysql_cursor = mysql_connection.cursor()
except Error as e:
    print(f"Error while connecting to MySQL: {e}")
# ------------------- 程序入口 -------------------
# ------------------- 程序入口 -------------------
if __name__ == "__main__":
    # 创建3个设备，每个设备设定不同模式
    devices = []
    for i in range(3):
        if i == 0:
            mode = "老年人步行"
        elif i == 1:
            mode = "年轻人步行"
        elif i == 2:
            mode = "运动员训练"
        devices.append(ShoeDevice(i, mode=mode))

    running = [True]
    global_connected = [True]

    # 启动数据生成和上传线程
    threads = []
    for device in devices:
        thread = threading.Thread(target=device_worker, args=(device, running, global_connected))
        thread.daemon = True
        thread.start()
        threads.append(thread)

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        running[0] = False
        for thread in threads:
            thread.join()
        print("程序已停止")